﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Windows.Storage;
using Windows.Storage.Streams;
using Onetube.Providers.Interfaces;
using System.IO;
using Onetube.Providers.YoutubeDownloader;

namespace Onetube.Providers
{
    public class FileStorageProvider : IFileStorageProvider
    {
        private readonly string fileName = "FileStorage.json";

        private readonly string downloadingFilename = "DownloadingFileStorage.json";
        public async Task<IEnumerable<Onetube.Entities.FileDownloadEntity>> GetAllSavedFilesAsync()
        {
            TaskCompletionSource<IEnumerable<Onetube.Entities.FileDownloadEntity>> taskcompletion = new TaskCompletionSource<IEnumerable<Onetube.Entities.FileDownloadEntity>>();

            StorageFolder localFolder = ApplicationData.Current.LocalFolder;
            try
            {
                // Getting JSON from file if it exists, or file not found exception if it does not  
                StorageFile textFile = await localFolder.GetFileAsync(fileName);
                IEnumerable<Onetube.Entities.FileDownloadEntity> result = null;
                using (IRandomAccessStream textStream = await textFile.OpenReadAsync())
                {
                    // Read text stream     
                    using (DataReader textReader = new DataReader(textStream))
                    {
                        //get size                       
                        uint textLength = (uint)textStream.Size;
                        await textReader.LoadAsync(textLength);
                        // read it                    
                        string jsonContents = textReader.ReadString(textLength);
                        // deserialize back to our product!  
                        result = JsonConvert.DeserializeObject<IEnumerable<Onetube.Entities.FileDownloadEntity>>(jsonContents);
                        // and show it     
                    }
                }

                taskcompletion.SetResult(result);
            }
            catch (Exception ex)
            {
                taskcompletion.SetResult(null);
            }

            return await taskcompletion.Task;
        }

        public async Task SaveFileAsync(Onetube.Entities.FileDownloadEntity file)
        {
            StorageFolder localFolder = ApplicationData.Current.LocalFolder;
            try
            {
                // Getting JSON from file if it exists, or file not found exception if it does not 
                await localFolder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);
                StorageFile textFile = await localFolder.GetFileAsync(fileName);
                IEnumerable<Onetube.Entities.FileDownloadEntity> result = null;
                using (IRandomAccessStream textStream = await textFile.OpenReadAsync())
                {
                    // Read text stream     
                    using (DataReader textReader = new DataReader(textStream))
                    {
                        //get size                       
                        uint textLength = (uint)textStream.Size;
                        await textReader.LoadAsync(textLength);
                        // read it                    
                        string jsonContents = textReader.ReadString(textLength);
                        // deserialize back to our product!  
                        result = JsonConvert.DeserializeObject<IEnumerable<Onetube.Entities.FileDownloadEntity>>(jsonContents);
                        // and show it     
                    }
                }

                List<Onetube.Entities.FileDownloadEntity> entities = new List<Onetube.Entities.FileDownloadEntity>();
                if (result != null)
                    
                    entities.AddRange(result);

                if (entities != null)
                {
                    entities.Add(file);

                    // Serialize our Product class into a string             
                    string jsonContents = JsonConvert.SerializeObject(entities);
                    // Get the app data folder and create or replace the file we are storing the JSON in.            
                   
                    textFile = await localFolder.CreateFileAsync(fileName,
                        CreationCollisionOption.ReplaceExisting);
                    // Open the file...      
                    using (IRandomAccessStream textStream = await textFile.OpenAsync(FileAccessMode.ReadWrite))
                    {
                        // write the JSON string!
                        using (DataWriter textWriter = new DataWriter(textStream))
                        {
                            textWriter.WriteString(jsonContents);
                            await textWriter.StoreAsync();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }

        public async Task DeleteFileAsync(Onetube.Entities.FileDownloadEntity file)
        {
            StorageFolder localFolder = ApplicationData.Current.LocalFolder;
            try
            {
                // Getting JSON from file if it exists, or file not found exception if it does not  
                StorageFile textFile = await localFolder.GetFileAsync(fileName);
                IEnumerable<Onetube.Entities.FileDownloadEntity> result = null;
                using (IRandomAccessStream textStream = await textFile.OpenReadAsync())
                {
                    // Read text stream     
                    using (DataReader textReader = new DataReader(textStream))
                    {
                        //get size                       
                        uint textLength = (uint)textStream.Size;
                        await textReader.LoadAsync(textLength);
                        // read it                    
                        string jsonContents = textReader.ReadString(textLength);
                        // deserialize back to our product!  
                        result = JsonConvert.DeserializeObject<IEnumerable<Onetube.Entities.FileDownloadEntity>>(jsonContents);
                        // and show it     
                    }
                }
                await Task.Delay(2000);
                if (result != null)
                {
                    var type = (Onetube.Providers.YoutubeDownloader.DownloadType)file.Type;
                    var item = result.FirstOrDefault(x => x.Type == (int)type && x.VideoDetails.Id.Equals(file.VideoDetails.Id));
                    if (type != null && item != null)
                    {
                        try
                        {
                        var onetubeFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("OnetubePro", CreationCollisionOption.OpenIfExists);
                        var videoFolder = await onetubeFolder.CreateFolderAsync("Videos", CreationCollisionOption.OpenIfExists);
                        var musicFolder = await onetubeFolder.CreateFolderAsync("Music", CreationCollisionOption.OpenIfExists);

                        switch (type)
                        {
                            case DownloadType.Video:
                                try
                                {
                                    var f = await videoFolder.GetFileAsync(item.Url);
                                   await f.DeleteAsync();
                                }
                                catch (Exception ex)
                                {
                                    
                                    
                                }
                                break;
                            case DownloadType.Audio:
                                try
                                {
                                    var f = await musicFolder.GetFileAsync(item.Url);
                                   await f.DeleteAsync();
                                }
                                catch (Exception ex)
                                {
                                    
                                    
                                }
                                break;
                            default:
                                break;
                        }
                            // TODO:Update
                            //IsolatedStorageFile media = IsolatedStorageFile.GetUserStoreForApplication();
                            //var filename = string.Format("{0}_{1}.mp4", item.VideoDetails.Id, type.ToString());
                            //if (media.FileExists("/shared/transfers/Videos/" + filename))
                            //{
                            //    media.DeleteFile("/shared/transfers/Videos/" + filename);
                            //}
                        }
                        catch (Exception)
                        {
                        }
                        var itemToRemove = result.Where(x => x.ID.Equals(item.ID));
                        if (itemToRemove != null)
                        {
                            var list = result.Except(itemToRemove);
                            if (list != null)
                            {
                                // Serialize our Product class into a string             
                                string jsonContents = JsonConvert.SerializeObject(list);
                                // Get the app data folder and create or replace the file we are storing the JSON in.            

                                textFile = await localFolder.CreateFileAsync(fileName,
                                    CreationCollisionOption.ReplaceExisting);
                                // Open the file...      
                                using (IRandomAccessStream textStream = await textFile.OpenAsync(FileAccessMode.ReadWrite))
                                {
                                    // write the JSON string!
                                    using (DataWriter textWriter = new DataWriter(textStream))
                                    {
                                        textWriter.WriteString(jsonContents);
                                        await textWriter.StoreAsync();
                                    }
                                }
                            }
                            else
                            {
                                textFile = await localFolder.CreateFileAsync(fileName,
                                    CreationCollisionOption.ReplaceExisting);
                                // Open the file...      
                                using (IRandomAccessStream textStream = await textFile.OpenAsync(FileAccessMode.ReadWrite))
                                {
                                    // write the JSON string!
                                    using (DataWriter textWriter = new DataWriter(textStream))
                                    {
                                        textWriter.WriteString("");
                                        await textWriter.StoreAsync();
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }

        public async Task<Uri> SaveImageAsync(Stream stream, string name)
        {
            if (stream != null && !string.IsNullOrEmpty(name))
            {
                try
                {
                    var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(name, CreationCollisionOption.ReplaceExisting);

                    using (IRandomAccessStream textStream = await file.OpenAsync(FileAccessMode.ReadWrite))
                    {
                        using (DataWriter writer = new DataWriter(textStream))
                        {
                            writer.WriteBytes(ReadStream(stream));
                        }
                    }

                    string path = string.Format("ms-appx:///{0}", name);
                    return new Uri(path);
                }
                catch (Exception ex)
                {
                    
                   
                }
              
            }
            return null;
        }

        public Task<byte[]> GetImageAsync(string name)
        {
            if (!string.IsNullOrEmpty(name))
            {

            }
            return null;
        }


        public static byte[] ReadStream(Stream input)
        {
            byte[] buffer = new byte[16 * 1024];
            using (MemoryStream ms = new MemoryStream())
            {
                int read;
                while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, read);
                }
                return ms.ToArray();
            }
        }


        public async Task SaveFileDownloadingAsync(YoutubeDownloader.DownloadItem item)
        {
            StorageFolder localFolder = ApplicationData.Current.LocalFolder;
            try
            {
                // Getting JSON from file if it exists, or file not found exception if it does not 
                await localFolder.CreateFileAsync(downloadingFilename, CreationCollisionOption.OpenIfExists);
                StorageFile textFile = await localFolder.GetFileAsync(downloadingFilename);
               List<DownloadItem> result = null;
                using (IRandomAccessStream textStream = await textFile.OpenReadAsync())
                {
                    // Read text stream     
                    using (DataReader textReader = new DataReader(textStream))
                    {
                        //get size                       
                        uint textLength = (uint)textStream.Size;
                        await textReader.LoadAsync(textLength);
                        // read it                    
                        string jsonContents = textReader.ReadString(textLength);
                        // deserialize back to our product!  
                        result = JsonConvert.DeserializeObject<List<DownloadItem>>(jsonContents);
                        // and show it     
                    }
                }

                List<DownloadItem> entities = new List<DownloadItem>();
                if (result != null)
                    
                    entities.AddRange(result);

                if (entities != null)
                {
                    if (entities.Any(x => x.ID.Equals(item.ID)))
                        return;

                    entities.Add(item);
                    // Serialize our Product class into a string             
                    string jsonContents = JsonConvert.SerializeObject(entities);
                    // Get the app data folder and create or replace the file we are storing the JSON in.            

                    textFile = await localFolder.CreateFileAsync(downloadingFilename,
                        CreationCollisionOption.ReplaceExisting);
                    // Open the file...      
                    using (IRandomAccessStream textStream = await textFile.OpenAsync(FileAccessMode.ReadWrite))
                    {
                        // write the JSON string!
                        using (DataWriter textWriter = new DataWriter(textStream))
                        {
                            textWriter.WriteString(jsonContents);
                            await textWriter.StoreAsync();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }

        public Task DeleteFileDownloadingAsync(YoutubeDownloader.DownloadItem item)
        {
           // throw new NotImplementedException();
            return null;
        }


        public async Task<IEnumerable<DownloadItem>> GetAllDownloadingFilesAsync()
        {
            TaskCompletionSource<IEnumerable<DownloadItem>> taskcompletion = new TaskCompletionSource<IEnumerable<DownloadItem>>();

            StorageFolder localFolder = ApplicationData.Current.LocalFolder;
            try
            {
                // Getting JSON from file if it exists, or file not found exception if it does not  
                StorageFile textFile = await localFolder.GetFileAsync(downloadingFilename);
                IEnumerable<DownloadItem> result = null;
                using (IRandomAccessStream textStream = await textFile.OpenReadAsync())
                {
                    // Read text stream     
                    using (DataReader textReader = new DataReader(textStream))
                    {
                        //get size                       
                        uint textLength = (uint)textStream.Size;
                        await textReader.LoadAsync(textLength);
                        // read it                    
                        string jsonContents = textReader.ReadString(textLength);
                        // deserialize back to our product!  
                        result = JsonConvert.DeserializeObject<IEnumerable<DownloadItem>>(jsonContents);
                        // and show it     
                    }
                }

                taskcompletion.SetResult(result);
            }
            catch (Exception ex)
            {
                taskcompletion.SetResult(null);
            }

            return await taskcompletion.Task;
        }
    }
}